﻿using JinianNet.JNTemplate;
using RuoVea.CodeGen.Dto;
using RuoVea.CodeGen.Util;
using RuoVea.ExIdGen;
using RuoVea.ExUtil;
using RuoVea.ExUtil.Exceptions;

namespace RuoVea.CodeGen.Controllers;

/// <summary>
/// 
/// </summary>
public partial class DbTableMetadataController : Controller
{
    /// <summary>
    /// 
    /// </summary>
    private readonly SugarRepository<DbTableMetadata> _thisRepository;
    private readonly List<DbConnectionConfig> _dbConnectionConfigs;
    private readonly ISqlSugarClient _defultDbContext;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="thisRepository"></param> 
    /// <param name="dbConnectionConfigs"></param> 
    public DbTableMetadataController(SugarRepository<DbTableMetadata> thisRepository, IOptions<List<DbConnectionConfig>> dbConnectionConfigs, ISqlSugarClient defultDbContext)
    {
        _thisRepository = thisRepository;
        _dbConnectionConfigs = dbConnectionConfigs.Value;
        _defultDbContext = defultDbContext;
    }


    public IActionResult Index()
    {
        return View();
    }

    /// <summary>
    /// 查询所有/分页
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [HttpPost("/TableMetadata/pages")]
    public async Task<RestfulResult<PageResult<DbTableMetadata>>> GetPagesAsync()
    {
        using var sr = new StreamReader(Request.Body);
        string dataStr = await sr.ReadToEndAsync();
        if (Request.Body.CanSeek)
            Request.Body.Position = 0;
        if (string.IsNullOrWhiteSpace(dataStr))
            throw new Exception("未提供上传数据。请在Request.Body中携带上传数据。");
        PageParam? data = JsonConvert.DeserializeObject<PageParam>(dataStr);
        data ??= new PageParam { PageNo = 1, PageSize = 10 };

        var restful = new RestfulResult<PageResult<DbTableMetadata>>() { Code = CodeStatus.OK };
        data ??= new PageParam { PageNo = 1, PageSize = 10 };
        var query = await _thisRepository.AsQueryable()
            .ToPageAsync(data.PageNo, data.PageSize);

        restful.Data = query;
        return restful;
    }

    /// <summary>
    /// 查询所有/分页
    /// </summary>
    /// <returns></returns>
    [HttpGet("/TableMetadata/list")]
    public async Task<RestfulResult<PageResult<DbTableMetadata>>> GetlistAsync()
    {
        var restful = new RestfulResult<PageResult<DbTableMetadata>>() { Code = CodeStatus.OK };
        PageParam data = new PageParam { PageNo = 1, PageSize = 100 };
        var query = await _thisRepository.AsQueryable()
            .ToPageAsync(data.PageNo, data.PageSize);
        restful.Data = query;
        return restful;
    }

    [HttpGet("/TableMetadata/TableDatas")]
    public RestfulResult<List<DbTableInfo>> TableDatas(long dbId)
    {
        var restful = new RestfulResult<List<DbTableInfo>>() { Code = CodeStatus.OK };
        restful.Data = _defultDbContext.DbMaintenance.GetTableInfoList();
        return restful;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbId"></param>
    /// <param name="dbTableInfos"></param>
    /// <returns></returns>
    /// <exception cref="ParamiterException"></exception>
    [HttpPost("/TableMetadata/InitMetadataData")]
    public async Task InitMetadataData([FromBody] InitMetadataRequest request)
    {
        var tableNames = request.dbTableInfos.Select(c => c.Name).ToList();
        var existingTableNames = _thisRepository.AsQueryable().Where(x => tableNames.Contains(x.TableName)).Select(x => x.TableName).ToList();
        if (existingTableNames.Any())
        {
            throw new ParamiterException($"以下表名已经存在: {string.Join(", ", existingTableNames)}.");
        }

        //if (request.dbId <= 0)
        //    throw new ParamiterException($"{{dbId}} 不存在这样的数据库配置.");
        foreach (var t in request.dbTableInfos)
        {
            string tableName = t.Name;
            if (!_defultDbContext.DbMaintenance.IsAnyTable(tableName))
                throw new ParamiterException($"{{tableName}} 不存在这样的表.");

            if (!_defultDbContext.DbMaintenance.IsAnyTable(nameof(DbTableMetadata)))
                _defultDbContext.CodeFirst.InitTables(typeof(DbTableMetadata));

            if (!_defultDbContext.DbMaintenance.IsAnyTable(nameof(FieldMetadata)))
                _defultDbContext.CodeFirst.InitTables(typeof(FieldMetadata));

            // 获取表结构
            List<DbColumnInfo> columns = _defultDbContext.DbMaintenance.GetColumnInfosByTableName(tableName);

            DbColumnInfo columnOne = columns.FirstOrDefault()!;

            DbTableMetadata tableMetadata = new DbTableMetadata()
            {
                DbId = request.dbId,
                TableName = columnOne.TableName,
                ClassName = columnOne.TableName,
                Id = IdGenerator.Id,
            };

            List<FieldMetadata> fieldMetadatas = new List<FieldMetadata>();
            List<FieldMetadataExAvue> fieldMetadataExAvues = new List<FieldMetadataExAvue>();
            
            var properties = typeof(IPrimaryKeyEntity).GetProperties().Select(x => x.Name.ToLower()).ToList();
            //properties.AddRange(typeof(IDeletedEntity).GetProperties().Select(x => x.Name.ToLower()).ToList());
            //properties.AddRange(typeof(IAuditableEntity).GetProperties().Select(x => x.Name.ToLower()).ToList());

            foreach (DbColumnInfo column in columns)
            {
                FieldMetadata fieldMetadata = new FieldMetadata();

                fieldMetadata.TableMetaId = tableMetadata.Id;

                fieldMetadata.DbColumnName = column.DbColumnName;
                //fieldMetadata.ClassName = CodeGenUtil.CamelColumnName( column.DbColumnName,null);

                fieldMetadata.PropertyType = CodeGenUtil.ConvertDataType(column, DbType.Sqlite);
                fieldMetadata.DataType = column.DataType;
                fieldMetadata.Length = column.Length;
                fieldMetadata.Description = column.ColumnDescription;

                fieldMetadata.DefaultValue = column.DefaultValue;
                fieldMetadata.IsNullable = column.IsNullable;
                fieldMetadata.IsPrimaryKey = column.IsPrimarykey;

                fieldMetadata.IsIdentity = column.IsIdentity;
                fieldMetadata.FieldSort = column.CreateTableFieldSort;

                fieldMetadata.PropertyName = column.DbColumnName;
                fieldMetadata.DecimalDigits = column.DecimalDigits;
                fieldMetadata.IsJson = column.IsJson;
                fieldMetadata.IsIgnore = false;

                fieldMetadata.Id = IdGenerator.Id;

                fieldMetadatas.Add(fieldMetadata);


                FieldMetadataExAvue fieldMetadataExAvue = new FieldMetadataExAvue
                {
                    Id = IdGenerator.Id,
                    TableMetaId= tableMetadata.Id,
                    FieldMetadataId = fieldMetadata.Id
                };
                fieldMetadataExAvues.Add(fieldMetadataExAvue);
            }

            try
            {
                await _defultDbContext.Ado.BeginTranAsync();
                await _defultDbContext.Insertable(tableMetadata).ExecuteCommandAsync();
                await _defultDbContext.Insertable(fieldMetadatas).ExecuteCommandAsync();
                await _defultDbContext.Insertable(fieldMetadataExAvues).ExecuteCommandAsync();
                await _defultDbContext.Ado.CommitTranAsync();
            }
            catch (Exception ex)
            {
                await _defultDbContext.Ado.RollbackTranAsync();
                new ParamiterException("初始化元数据表和数据异常.", ex);
            }
        }
    }
    /// <summary>
    /// 增加
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [UnitOfWork]
    [HttpPost("/TableMetadata/add")]
    public async Task<RestfulResult> AddAsync([FromBody] DbTableMetadata data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        bool result = await _thisRepository.InsertAsync(data);
        if (result)
        {
            restful.Data = result;
            restful.Code = CodeStatus.OK;
            return restful;
        }
        else
        {
            restful.Message = "添加失败";
            return restful;
        }
    }

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [HttpPost("/TableMetadata/update")]
    public async Task<RestfulResult> UpdateAsync([FromBody] DbTableMetadata data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        bool result = await _thisRepository.UpdateAsync(data, true, true, "笔记修改");
        if (result)
        {
            restful.Data = result;
            restful.Code = CodeStatus.OK;
            return restful;
        }
        else
        {
            restful.Message = "修改失败";
            return restful;
        }
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [HttpDelete("/TableMetadata/delete")]
    public async Task<RestfulResult> DeleteAsync([FromBody] EntityBaseId data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };

        if (data.Id == 0)
        {
            restful.Message = "删除失败";
            return restful;
        }

        try
        {
            await _defultDbContext.Ado.BeginTranAsync();

            bool isDelete = await _thisRepository.DeleteByIdAsync(data.Id);
            isDelete = _thisRepository.Change<FieldMetadata>().Delete(x => x.TableMetaId == data.Id);
            isDelete = _thisRepository.Change<FieldMetadataExAvue>().Delete(x => x.TableMetaId == data.Id);
            await _defultDbContext.Ado.CommitTranAsync();
            if (isDelete)
            {
                restful.Data = isDelete;
                restful.Message = "删除成功";
                restful.Code = CodeStatus.OK;
                return restful;
            }
            else
            {
                restful.Data = isDelete;
                restful.Message = "删除失败";
                return restful;
            }
        }
        catch (Exception ex)
        {
            await _defultDbContext.Ado.RollbackTranAsync();
            restful.Data = false;
            restful.Message = "删除失败" + ex.Message;
            return restful;
        }
    }


    [HttpPost("/TableMetadata/codeBuild")]
    public RestfulResult CodeBuild([FromBody] CodeBuildRequest request)
    {
        RestfulResult restful = new() { Code = CodeStatus.OK };
        try
        {
            DbTableMetadata dbTableMetadata = _thisRepository.AsQueryable()
                .Where(x => x.TableName == request.TableName && x.DbId == request.ConfigId)
                .Includes(x => x.Propertys).First();

            dbTableMetadata.Description = dbTableMetadata.Description ?? dbTableMetadata.ClassName;
            // 获取表结构
            string content = _thisRepository.Change<FileTemplate>().AsQueryable().Where(x => x.Id == request.TemplateId).Select(x => x.Content).First();
            //// 加载模板
            var template = JNTemplateEx.CreateTemplate(content);

            // 设置模板变量
            template.Set("Model", dbTableMetadata);

            // 渲染模板
            var result = template.Render();
            restful.Data = result;
        }
        catch (Exception ex)
        {
            restful.Message = ex.Message;
            restful.Code = CodeStatus.BadRequest;
        }
        return restful;
    }
}
